﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ClusterAggregation.GeneralTools
{
    /**
     * CMatrixOperators is a class that holds general operators for matrix (add, divide, mult etc).
     * Most of it's methods are static, so they can be used without instantiating the class.
     */
    class CMatrixOperators
    {
        /**
         * resets a matrix to zeroes.
         * @param mat (double[,]) [INOUT] the matrix on which we work.
         * @param n (int) [IN] states the number of rows
         * @param m (int) [IN] states the number of columns
         */
        public static void resetMat(ref double[,] mat, int n, int m)
        {
            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j < m; j++)
                {
                    mat[i, j] = 0;
                }
            }
        }

        /**
         * divides each cell in the matrix by a scalar value.
         * @param mat (double[,]) [INOUT] the matrix on which we work.
         * @param n (int) [IN] states the number of rows
         * @param m (int) [IN] states the number of columns
         * @param arg (double) [IN] the value by which we divide.
         */
        public static void divMat(ref double[,] mat, int n, int m, double arg)
        {
            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j < m; j++)
                {
                    mat[i, j] /= arg;
                }
            }
        }
        /**
         * Multiplies 2 matrices.
         * @param rez (double[,]) [OUT] the output matrix.
         * @param a (double[,]) [IN] the left matrix, should be size NxK (both defined by user)
         * @param b (double[,]) [IN] the right matrix, should be size Kxm (both defined by user)
         * @param n (int) [IN] states the number of rows in left matrix
         * @param k (int) [IN] states the number of cols in left matrix and number of rows in right matrix.
         * @param m (int) [IN] states the number of columns in right matrix
         */
        public static void multMatrices(out double[,] rez, double[,] a, double[,] b, int n, int k, int m)
        {
            rez = new double[n, m];
            resetMat(ref rez, n, m);

            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j < m; j++)
                {
                    for (int l = 0; l < k; l++)
                    {
                        rez[i, j] += a[i, l] * b[l, j];
                    }
                }
            } // end of for i
        }

        /**
         * Adds 2 matrices together (left = left+right)
         * @param mat (double[,]) [INOUT] the matrix on which we work.
         * @param secondmat (double[,]) [IN] the right matrix.
         * @param n (int) [IN] states the number of rows
         * @param m (int) [IN] states the number of columns
         */
        public static void addToFirst(ref double[,] mat, double[,] secondmat, int n, int m)
        {
            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j < m; j++)
                {
                    mat[i, j] += secondmat[i, j];
                }
            }
        }

    }
}
